package com.inspinia.base.util;

import org.apache.commons.io.IOUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;

import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 压缩，解压zip
 * Created by lijr on 2016/9/7.
 * 使用方法：
 * <p>
 * <p>
 * <p>
 * 压缩文件
 * File[] files1 = new File[]{new File("G:/build.xml"),new File("G:/test.txt"),new File("G:/一样.doc"),new File("G:/testexcel.xls")};
 * File[] files2 = new File[]{new File("G:/sharedFolder")};
 * File zip = new File("G:/压缩.zip");
 * ZipFiles(zip,"abc",files1);
 * File zip = new File("G:/压缩sharedFolder.zip");
 * ZipFiles(zip,"",files2);
 * 解压文件
 * File zipFile = new File("G:/压缩.zip");
 * String path = "G:/zipfile/";
 * unZipFiles(zipFile, path);
 * </p>
 */
public class ZipFilesUtil {

    /**
     * 压缩文件-由于out要在递归调用外,所以封装一个方法用来
     * 调用ZipFiles(ZipOutputStream out,String path,File... srcFiles)
     *
     * @param zip      压缩包文件
     * @param path     压缩包中文件的存放地址
     * @param srcFiles 压缩的文件或者文件夹
     * @throws IOException
     */
    public static void ZipFiles(File zip, String path, File... srcFiles) throws IOException {
        if (!zip.exists()) {
            zip.createNewFile();
        }
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zip));
        ZipFiles(out, path, srcFiles);
        out.close();
        System.out.println("*****************压缩完毕*******************");
    }

    /**
     * 压缩文件-File
     *
     * @param out      压缩包的输出流
     * @param path     压缩包中文件的存放地址
     * @param srcFiles 被压缩源文件或文件夹
     */
    public static void ZipFiles(ZipOutputStream out, String path, File... srcFiles) {
        path = path.replaceAll("\\*", "/");
        if (!path.endsWith("/")) {
            path += "/";
        }
        byte[] buf = new byte[1024];
        try {
            for (int i = 0; i < srcFiles.length; i++) {
                if (srcFiles[i].isDirectory()) {
                    File[] files = srcFiles[i].listFiles();
                    String srcPath = srcFiles[i].getName();
                    srcPath = srcPath.replaceAll("\\*", "/");
                    if (!srcPath.endsWith("/")) {
                        srcPath += "/";
                    }
                    out.putNextEntry(new ZipEntry(path + srcPath));
                    ZipFiles(out, path + srcPath, files);
                } else {
                    FileInputStream in = new FileInputStream(srcFiles[i]);
                    System.out.println(path + srcFiles[i].getName());
                    if (!path.equals("/")) {
                        out.putNextEntry(new ZipEntry(path + srcFiles[i].getName()));
                    } else {
                        out.putNextEntry(new ZipEntry(srcFiles[i].getName()));
                    }
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    out.closeEntry();
                    in.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压到指定目录
     *
     * @param zipPath 压缩包路径
     * @param descDir 文件夹路径
     */
    public static void unZipFiles(String zipPath, String descDir) throws IOException {
        unZipFiles(new File(zipPath), descDir);
    }


    /**
     * @param filePath 带逗号分隔的 文件路劲
     * @param times    信息流和资金流 反馈的时候 保证 2个表的路劲值一样 用的时间戳来存 此处保存 之前的时间戳
     * @param type     类型  资金流 三侦 还是 信息流
     * @return
     */
    public static String getZipFileByfiles(String filePath, String times, String type, String uploadPath, String zipSuffix) {
        if (filePath.indexOf(",") > 0) {
            //字符串中包含逗号 有分隔符 为多文件上传
            //例：netTech/20170215/1487147949258098708_信息犯罪线索追查分析系统介绍.doc,netTech/20170215/1487147956137072754_前端开发规范.doc
            String[] filePathArr = filePath.split(",");
            Integer fileSize = filePathArr.length;
            File[] files1 = new File[fileSize];//要解压的文件数组
            String goalFileName = filePathArr[0].substring(0, filePathArr[0].lastIndexOf("/") + 1) + (type + "_" + times) + zipSuffix;
            File zipFile = new File(uploadPath + "/" + goalFileName);
            for (int i = 0; i < fileSize; i++) {
                String fileName = filePathArr[i];//取上传后的文件的名字 
                files1[i] = new File(uploadPath + "/" + fileName);
            }
            try {
                ZipFilesUtil.ZipFiles(zipFile, "", files1); //压缩文件
            } catch (IOException e) {
                e.printStackTrace();
            }
            filePath = goalFileName;
            FileUtil.deleteFiles(filePathArr, uploadPath);//********删除压缩文件里面的原文件***
        }
        return filePath;
    }


    /**
     * 解压文件到指定目录
     *
     * @param zipFile 压缩包
     * @param descDir 文件夹路径
     */
    public static void unZipFiles(File zipFile, String descDir) throws IOException {
        File pathFile = new File(descDir);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        ZipFile zip = new ZipFile(zipFile);
        for (Enumeration entries = zip.getEntries(); entries.hasMoreElements(); ) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String zipEntryName = entry.getName();
            InputStream in = zip.getInputStream(entry);
            String outPath = (descDir + zipEntryName).replaceAll("\\*", "/");
            //判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            if (!file.exists()) {
                file.mkdirs();
            }
            //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
            if (new File(outPath).isDirectory()) {
                continue;
            }
            //输出文件路径信息
            System.out.println(outPath);

            OutputStream out = new FileOutputStream(outPath);
            byte[] buf1 = new byte[1024];
            int len;
            while ((len = in.read(buf1)) > 0) {
                out.write(buf1, 0, len);
            }
            in.close();
            out.close();
        }
        System.out.println("******************解压完毕********************");
    }


    /**
     * 解压文件到指定目录
     *
     * @param bufr    压缩包
     * @param descDir 文件夹路径
     */
    public static void unZipOutputStream(BufferedReader bufr, String descDir) throws IOException {
        File pathFile = new File(descDir);
        if (!pathFile.exists()) {
            pathFile.createNewFile();
        }
        //ZipOutputStream zos = new ZipOutputStream();
        OutputStream out = new FileOutputStream(descDir);
        BufferedWriter writer = new BufferedWriter(new FileWriter(descDir));
        writer.write(bufr.read());
        out.close();
        writer.close();
        bufr.close();
    }


    /**
     * 执行压缩文件的解压,并自动生成文件的操作
     *
     * @param in
     * @param outputDirectory
     * @return
     */
    public static Map<String, Object> unZipInputStream(InputStream in, String outputDirectory) {

        if (in == null) {
            return null;
        }

        java.util.zip.ZipEntry zipEntry = null;
        FileOutputStream out = null;
        String uniqueName, iconUrl = null;
        Map<String, Object> map = new HashMap<String, Object>();
        ZipInputStream zipIn = new ZipInputStream(in);
        try {
            while ((zipEntry = zipIn.getNextEntry()) != null) {
                //如果是文件夹路径方式，本方法内暂时不提供操作
                if (zipEntry.isDirectory()) {
                    String name = zipEntry.getName();
                    name = name.substring(0, name.length() - 1);
                    File file = new File(outputDirectory + File.separator + name);
                    file.mkdir();
                } else {
                    //如果是文件，则直接在对应路径下生成
                    uniqueName = zipEntry.getName();
                    File path = new File(outputDirectory + File.separator);
                    if (!path.exists()) {
                        path.mkdirs();
                    }

                    iconUrl = outputDirectory + File.separator + uniqueName;
                    File file = new File(iconUrl);
                    file.createNewFile();
                    out = new FileOutputStream(file);
                    int b = 0;
                    while ((b = zipIn.read()) != -1) {
                        out.write(b);
                    }
                    out.close();
                    map.put(zipEntry.getName(), iconUrl);
                }
            }
            return map;
        } catch (Exception ex) {
            return null;
        } finally {
            IOUtils.closeQuietly(zipIn);
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 根据传递的文件名(带后缀)生成唯一新文件名(带后缀)
     * @return
     */
//    private static String getSavedFileName(String origFileName) {
//        return getCurrentTimeStamp("yyyyMMddHHmmss") + "-" + RandomStringUtils.randomNumeric(5) + "." + FilenameUtils.getExtension(origFileName);
//    }
}
